use crate::cljcell::clj_cell::CljCell;
use crate::lexer::clj_code_to_chars::CljCharIterator;
use crate::util::clj_util::check_number_type;
use crate::cljcell::clj_cell::add;
use crate::util::clj_util::NumberType;
use std::rc::Rc;

/**
 * Lexer
 * */
pub struct CljLexer<'a> {
    my_char_iterator: CljCharIterator<'a>,
    token: CljCell
}

impl <'a> CljLexer<'a> {
    pub fn new(my_char_iterator: CljCharIterator<'a>) -> Self {
        Self {
            token: CljCell::Null,
            my_char_iterator: my_char_iterator
        }
    }

    /**
     * 当前 token
     * */
    pub fn current(&self) -> &CljCell {
        &self.token
    }

    // pub fn current(&self) -> &Box<CljCell> {
    //     //Box::new(self.token.clone())
    //     &self.token
    // }

    pub fn chars_to_int(&self, chars: Vec<char>) -> Option<i32> {
        let s: String = chars.into_iter().collect();
        s.parse::<i32>().ok() // 返回 Option<i32>
    }

    pub fn get_string(&mut self) -> Result<String, &'a str> {
        let mut sb = String::new();
        // 移动到 " 的后一个字符
        self.my_char_iterator.next();
        loop {
            let mut c: char = self.my_char_iterator.current();
            if c == '"' {
                return Ok(sb);
            } else if c == '\n' {
                //return Err("string not terminated: ".to_owned() + CljUtil::toStr(sb));
                return Err("string not terminated ");
            }

            sb.push(c);
            self.my_char_iterator.next();
        }
    }

    pub fn next(&mut self) -> bool {
        let m = self.next_token();
        if m.is_ok() == true {
            self.token = m.unwrap();
            return true;
        }
        return false;
    }

    /**
     * 下一个 token
     * */
    pub fn next_token(&mut self) -> Result<CljCell, &str> {
        let mut c:char;
        /**
         * 剔除空格和注释
         * */
        loop {
            // 如果是空格就继续移动到非空格
            while self.my_char_iterator.current().is_whitespace() {
                self.my_char_iterator.next();
            }

            // 剔除 lisp 中的注释
            // 在 lisp 中注释是以 ; 开头， \n 结尾的
            c = self.my_char_iterator.current();
            if c == ';' {
                self.my_char_iterator.next();
                while self.my_char_iterator.current() != '\n' {
                    self.my_char_iterator.next();
                }
            } else {
                break;
            }
        }

        match c {
            '~' => {
                self.my_char_iterator.next();
                if self.my_char_iterator.current() == '@' {
                    self.my_char_iterator.next();
                    return Ok(CljCell::UnquoteList);
                }
                return Ok(CljCell::Unquote);
            },
            '=' => {
                self.my_char_iterator.next();
                return Ok(CljCell::EqualsLgClj);
            },
            '>' => {
                self.my_char_iterator.next();
                if self.my_char_iterator.current() == '=' {
                    self.my_char_iterator.next();
                    return Ok(CljCell::GreaterEqualsLgClj);
                }
                return Ok(CljCell::GreaterThanLgClj);
            },
            '<' => {
                self.my_char_iterator.next();
                if self.my_char_iterator.current() == '=' {
                    self.my_char_iterator.next();
                    return Ok(CljCell::LessEqualsLgClj);
                }
                return Ok(CljCell::LessThanLgClj);
            },
            '#' => {
                self.my_char_iterator.next();
                return Ok(CljCell::Sharp);
            },
            '%' => {
                self.my_char_iterator.next();
                let mut lstc: Vec<char> = Vec::new();
                while self.my_char_iterator.current().is_digit(10) {
                    lstc.push(self.my_char_iterator.current());
                    self.my_char_iterator.next();
                }

                if lstc.len() > 0 {
                    let n = self.chars_to_int(lstc).unwrap();
                    return Ok(CljCell::Percent(Some(Box::new(CljCell::IntClj (n)))));
                    //return Ok(CljCell::Percent{vs_index: vec![CljCell::IntClj (n)], has_vs: true});
                }
                return Ok(CljCell::Percent(Some(Box::new(CljCell::IntClj (1)))));
                //return Ok(CljCell::Percent{vs_index: vec![CljCell::IntClj (1)], has_vs: true});
            },
            '(' => {
                self.my_char_iterator.next();
                return Ok(CljCell::LparenClj);
            },
            ')' => {
                self.my_char_iterator.next();
                return Ok(CljCell::RparenClj);
            },
            '\'' => {
                self.my_char_iterator.next();
                return Ok(CljCell::Quote);
            },
            '`' => {
                self.my_char_iterator.next();
                return Ok(CljCell::QuoteList);
            },
            '[' => {
                self.my_char_iterator.next();
                return Ok(CljCell::LbracketClj);
            },
            ']' => {
                self.my_char_iterator.next();
                return Ok(CljCell::RbracketClj);
            },
            '{' => {
                self.my_char_iterator.next();
                return Ok(CljCell::LbracesClj);
            },
            '}' => {
                self.my_char_iterator.next();
                return Ok(CljCell::RbracesClj);
            },
            '"' => {
                let s1 = self.get_string();
                self.my_char_iterator.next();
                return Ok(CljCell::StringClj (Rc::new(s1.unwrap().to_string())));
            },
            '&' => {
                self.my_char_iterator.next();
                return Ok(CljCell::AndClj);
            },
            '+' => {
                self.my_char_iterator.next();
                return Ok(CljCell::Addition);
            },
            '-' => {
                self.my_char_iterator.next();
                return Ok(CljCell::Subtraction);
            },
            '*' => {
                self.my_char_iterator.next();
                return Ok(CljCell::Multiplication);
            },
            '/' => {
                self.my_char_iterator.next();
                return Ok(CljCell::Division);
            },
            _ => {
                let mut sb = String::new();
                loop {
                    sb.push(c);
                    if self.my_char_iterator.next() == false {
                        break;
                    }

                    c = self.my_char_iterator.current();
                    if c == '(' || c == ')' || c == '\'' || c == '[' || c == ']' || c == '"' || c == '~' || c.is_whitespace() {
                        break;
                    }
                }

                if "nil".eq(&sb) {
                    return Ok(CljCell::Nil);
                } else {
                    let num = check_number_type(&sb);
                    match num {
                        NumberType::Integer{vs_i} => return Ok(CljCell::LongClj (vs_i)),
                        NumberType::Double{vs_f} => return Ok(CljCell::DoubleClj (vs_f)),
                        NumberType::Invalid => {
                            let first_char = sb.chars().next();
                            if first_char.is_some() && first_char.unwrap().eq(&':') {
                                let tail = sb.chars().skip(1).collect::<String>();
                                if tail.eq(&"else") {
                                    return Ok(CljCell::ElseClj);
                                } else {
                                    return Ok(CljCell::KeySymbol (Rc::new(sb)));
                                }
                            }
                            match sb.as_str() {
                                "defmacro" => return Ok(CljCell::Defmacro),
                                "defn" => return Ok(CljCell::Defn),
                                "def" => return Ok(CljCell::DefClj),
                                "fn" => return Ok(CljCell::FnClj),
                                "let" => return Ok(CljCell::LetClj),
                                "cond" => return Ok(CljCell::Cond),
                                "if" => return Ok(CljCell::IfClj),
                                "first" => return Ok(CljCell::FirstClj),
                                "last" => return Ok(CljCell::LastClj),
                                "rest" => return Ok(CljCell::RestClj),
                                "do" => return Ok(CljCell::DoClj),
                                "loop" => return Ok(CljCell::LoopClj),
                                "recur" => return Ok(CljCell::Recur),
                                "apply" => return Ok(CljCell::Apply),
                                "map" => return Ok(CljCell::MapClj),
                                "cons" => return Ok(CljCell::Cons),
                                "reduce" => return Ok(CljCell::ReduceClj),
                                "eval" => return Ok(CljCell::Eval),
                                "true" => return Ok(CljCell::BooleanClj (true)),
                                "false" => return Ok(CljCell::BooleanClj (false)),
                                "string_func" => return Ok(CljCell::StringFunc),
                                "number_func" => return Ok(CljCell::NumberFunc),
                                "boolean_func" => return Ok(CljCell::BooleanFunc),
                                "date_func" => return Ok(CljCell::DateFunc),
                                "int_func" => return Ok(CljCell::IntFunc),
                                "long_func" => return Ok(CljCell::LongFunc),
                                "char_func" => return Ok(CljCell::CharFunc),
                                "short_func" => return Ok(CljCell::ShortFunc),
                                "byte_func" => return Ok(CljCell::ByteFunc),
                                "double_func" => return Ok(CljCell::DoubleFunc),
                                "float_func" => return Ok(CljCell::FloatFunc),
                                "not" => return Ok(CljCell::NotClj),
                                "nil?" => return Ok(CljCell::IsNil),
                                "and" => return Ok(CljCell::AndLgClj),
                                "or" => return Ok(CljCell::OrLgClj),
                                ":else" => return Ok(CljCell::ElseClj),
                                //"println" => return Ok(CljCell::PrintlnClj),
                                _ => return Ok(CljCell::Symbol (Rc::new(sb))),
                            }
                        },
                    }
                }
            }
        }

        //return Ok(CljCell::Null);
    }

    /**
     * 当前行号
     * */
    pub fn get_line_number(&self) -> usize {
        self.my_char_iterator.get_line_number()
    }

    /**
     * 当前行 index
     * */
    pub fn get_line_index(&self) -> usize {
        self.my_char_iterator.get_line_index()
    }
}

pub fn my_println(a:i32, b:i32) {
    let my = CljCell::Sharp;
    println!("{:?}", my);
    println!("{:?}", add(a, b));
}
















































